package com.study.shengsiyuan.example09;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.security.SecureRandom;

import org.junit.Test;

public class _1_NIOTest {
	//buffer 的聚合/分散  gathering/scattering
	@Test
	public void test10() throws IOException {
		RandomAccessFile random = new RandomAccessFile("src/main/java/com/shengsiyuan/netty/example08/input.txt","rw");
		FileChannel  fc= random.getChannel();
		FileLock  fl = fc.lock(3, 6, true);
		System.out.println("valid : "+fl.isValid());
		System.out.println("lock type : "+fl.isShared());
		fl.close();
		random.close();
	}

	//文件锁  共享 /排他
	@Test
	public void test9() throws IOException {
		RandomAccessFile random = new RandomAccessFile("src/main/java/com/shengsiyuan/netty/example08/input.txt","rw");
		FileChannel  fc= random.getChannel();
		FileLock  fl = fc.lock(3, 6, true);
		System.out.println("valid : "+fl.isValid());
		System.out.println("lock type : "+fl.isShared());
		fl.close();
		random.close();
	}

	//内存映射文件  堆外内存  即操作系统内存
	//就是磁盘文件的数据 映射到内存中  ，对文件的操作，只需要操作此文件的内存映射操作即可反映到磁盘文件中
	@Test
	public void test8() throws IOException {
		RandomAccessFile random = new RandomAccessFile("src/main/java/com/shengsiyuan/netty/example08/input.txt","rw");
		FileChannel  fc= random.getChannel();
		//得到内存映射文件
		MappedByteBuffer  mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 5);

		mbb.put(0,(byte)'a');
		mbb.put(3,(byte)'b');
		random.close();
	}


	//只读buffer :  XXXbufferR
	@Test
	public void test7() throws IOException {
		ByteBuffer bb = ByteBuffer.allocate(10);
		for(int i=0;i<bb.capacity();i++) {
			bb.put((byte)i);
		}
		ByteBuffer bbr = bb.asReadOnlyBuffer();
	}


	//slice() 截取原有buffer部分数据，生成新buffer
	// 新旧buffer 共同部分数据 是同一块内存地址
	//理解   ： 新buffer 就是 旧buffer部分数据的快照或者引用
	//无论修改新旧buffer 都会反映到另一个buffer中，因为他们内存地址是一样的
	@Test
	public void test6() throws IOException {
		ByteBuffer bb = ByteBuffer.allocate(10);
		for(int i=0;i<bb.capacity();i++) {
			bb.put((byte)i);
		}
		bb.position(2);
		bb.limit(6);
		ByteBuffer b2 = bb.slice();
	}

	//必须存什么类型  就得取出什么类型 ，否则数据出错
	@Test
	public void test5() throws IOException {
		ByteBuffer bb = ByteBuffer.allocate(64);
		bb.putInt(15);
		bb.putLong(500000l);
		bb.putDouble(14.123);
//		bb.putChar('你');
		bb.putShort((short)3);
		bb.flip();

		System.out.println(bb.getInt());
		System.out.println(bb.getLong());
		System.out.println(bb.getDouble());
		System.out.println(bb.getChar());
		System.out.println(bb.getShort());
	}
	@Test
	public void test4() throws IOException {
		FileInputStream fis =new FileInputStream("src/main/java/com/shengsiyuan/netty/example08/input.txt");
		FileOutputStream fos =new FileOutputStream("src/main/java/com/shengsiyuan/netty/example08/input2.txt");
		FileChannel fic = fis.getChannel();
		FileChannel foc = fos.getChannel();
		ByteBuffer bb = ByteBuffer.allocate(1024);
		int read=0;
		while((read = fic.read(bb)) !=-1) {
			bb.flip();
			foc.write(bb);
			bb.clear();
		}
	}


	@Test
	public void test3() throws IOException {

		FileOutputStream fos =new FileOutputStream("src/main/java/com/shengsiyuan/netty/example08/nio2.txt");
		FileChannel fc = fos.getChannel();
		ByteBuffer bb = ByteBuffer.allocate(512);
		byte[] b ="hello word  haha".getBytes();
		for(int i=0;i<b.length;i++) {
			bb.put(b[i]);
		}
		bb.flip();
		fc.write(bb);
		fos.close();
	}

	@Test
	public void test2() throws IOException {
		FileInputStream fis =new FileInputStream("src/main/java/com/shengsiyuan/netty/example08/nio.txt");
		FileChannel fc = fis.getChannel();
		ByteBuffer bb = ByteBuffer.allocate(512);
		fc.read(bb);
		bb.flip();
		while(bb.remaining()>0) {
			byte b = bb.get();
			System.out.print(" "+(char)b +" ");
		}
		System.out.println();
		bb.flip();
		bb.put(0, (byte)'b');
		bb.flip();
		fc.write(bb);
		fis.close();
	}
	@Test
	public void test1() {
		IntBuffer buf = IntBuffer.allocate(10);
		for(int i=0;i<buf.capacity();i++) {
			int random = new SecureRandom().nextInt(20);
			buf.put(random);
		}
		buf.flip();
		while(buf.hasRemaining()) {
			System.out.println( buf.get() );
		}
	}

	@Test
	public void test() {
		IntBuffer buf = IntBuffer.allocate(10);
		System.out.println("------- 初始化状态");
		System.out.println("position : "+buf.position()+" ; limit : "+buf.limit()+" ; capacity : " +buf.capacity());
		for(int i=0;i<buf.capacity()-2;i++) {
			int random = new SecureRandom().nextInt(20);
			buf.put(random);
		}
		System.out.println("------- 读入数据后");
		System.out.println("position : "+buf.position()+" ; limit : "+buf.limit()+" ; capacity : " +buf.capacity());
		buf.flip();
		System.out.println("------- 写出数据前");
		System.out.println("position : "+buf.position()+" ; limit : "+buf.limit()+" ; capacity : " +buf.capacity());
		while(buf.hasRemaining()) {
			buf.get();
//			System.out.println( buf.get() );
		}
		System.out.println("------- 写出数据后");
		System.out.println("position : "+buf.position()+" ; limit : "+buf.limit()+" ; capacity : " +buf.capacity());
		buf.flip();
		System.out.println("------- 重新读入数据");
		System.out.println("position : "+buf.position()+" ; limit : "+buf.limit()+" ; capacity : " +buf.capacity());
		for(int i=0;i<buf.capacity()-3;i++) {
			int random = new SecureRandom().nextInt(20);
			buf.put(random);
		}
		System.out.println("------- 重新读入数据后");
		System.out.println("position : "+buf.position()+" ; limit : "+buf.limit()+" ; capacity : " +buf.capacity());
		buf.flip();
		System.out.println("------- 写出数据前");
		System.out.println("position : "+buf.position()+" ; limit : "+buf.limit()+" ; capacity : " +buf.capacity());

		buf.clear();
		System.out.println("------- buf.clear()后");
		System.out.println("position : "+buf.position()+" ; limit : "+buf.limit()+" ; capacity : " +buf.capacity());
	}
}
